/*
JETware Hands-free Extension provides additional features for Windows Mobile HFP support.
Copyright (C) 2004-2009 Jim Thatcher

This program is free software; you can redistribute it and/or modify it under the terms of the 
GNU General Public License as published by the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; 
if not, write to the Free Software Foundation, Inc., 
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Source Control header

$Workfile: JetBTConfig.cpp $
$Revision: 1 $
$Date: 1/1/09 1:11p $
*/
// JetBTConfig.cpp : Defines the entry point for the application.
//

#include <windows.h>
#include <windowsx.h>
#include <aygshell.h>
#include "resource.h"
#include <pimstore.h>
#include <initguid.h>
#include <objbase.h>
#include <tpcshell.h>
#include <htmlctrl.h>
#include "JetBTConfig.h"
#include <bthutil.h>
#include <mapidefs.h>
#include <mapicode.h>
#include <mapitags.h>
#include <mapix.h>
#include <mapiutil.h>
#include "uniqueid.h"
#include "Kfuncs.h"
#include <tapi.h>
#include <extapi.h>
#include "commdlg.h"
#include "urlmon.h"
#include "winsock2.h"
// #include <cemapi.h>

// Reg keys/values for checking registration of voice dial app
#define VC_BUTTON_KEY		_T("ButtonApps\\Microsoft\\Voice Command")
#define OEM_VOICE_APP		_T("Software\\OEM\\VoiceCommand")
#define VC_PATH				_T("AppFilePath")
#define VC_ARGS				_T("Parameters")
#define OEM_PATH			_T("Path")
#define AG_CAPABILTY		_T("Capability")

#define SAPI_KEY			_T("Software\\Microsoft\\Speech")
#define SAPI_ENGINE			_T("Engine")


// #ifndef RELEASE_OBJ
#define RELEASE_OBJ(s)\
    if (s != NULL)\
    {                   \
        s->Release();   \
        s = NULL;       \
    }
// #endif //RELEASE_OBJ


IPOutlookApp * g_polApp = NULL;
IFolder * g_pContactsFolder = NULL;
int g_nNumContacts = 0;

HINSTANCE g_hInst = NULL;  // Local copy of hInstance
static SHACTIVATEINFO s_sai;

#define ARRAYSIZE(a)   (sizeof(a)/sizeof(*a))

HWND g_hWndMain;
HWND g_hWndListView = NULL;

DEFINE_GUID(CLSID_Application, 0x05058F23, 0x20BE, 0x11d2, 0x8F, 0x18, 0x00, 0x00, 0xF8, 0x7A, 0x43, 0x35);
DEFINE_GUID(IID_IPOutlookApp, 0x05058F22, 0x20BE, 0x11d2, 0x8F, 0x18, 0x00, 0x00, 0xF8, 0x7A, 0x43, 0x35);

TCHAR g_szMessage[30];

BOOL CALLBACK MainDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);
BOOL CALLBACK RegisterDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);
BOOL CALLBACK PhonebookDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);
BOOL CALLBACK MessagingDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);
BOOL CALLBACK CategoriesDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);
BOOL CALLBACK FeaturesDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);
BOOL CALLBACK AboutDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);

#define szNoCat _T("(contacts with no categories)")
#define szNone _T("(none)")

/***********************************************************************
	  
FUNCTION: 
lineCallbackFunc

PURPOSE: 
This is a callback function invoked to determine status and events on
the line device, addresses, or calls. 
		  
***********************************************************************/
VOID CALLBACK lineCallbackFunc (
    DWORD hDevice, 
    DWORD dwMsg, 
    DWORD dwCallbackInstance,
    DWORD dwParam1, 
    DWORD dwParam2, 
    DWORD dwParam3
    )
{
#ifdef DEBUG
	CHAR szReport[64];
	sprintf(szReport, "lineCallbackFunc msg %8.8X-%8.8X-%8.8X : %8.8X", dwMsg, dwParam1, dwParam2, hDevice);
	LogString(szReport);
#endif
/*
	switch (dwMsg)
	{
		default:
			break;
	}
*/
	return;
}

TCHAR g_szModel[64];
TCHAR g_szMfr[64];
TCHAR g_szVersion[32];
TCHAR g_szHWID[32];
TCHAR g_szAppPath[MAX_PATH];
TCHAR g_szDllPath[MAX_PATH];
HLINE g_hVoiceLine = NULL;

void ShowExpiredMessage(HWND hParent)
{
	MessageBox(hParent, _T("Your evaluation period has expired.  Please purchase a license to continue using the JETware Hands-free Extension."), _T("Warning"), MB_OK);
}

DWORD GetPhoneInfo()
{
	DWORD dwRet = 0;
	DWORD dwSize = sizeof(LINEGENERALINFO);
	LPLINEGENERALINFO pInfo = NULL;
    DWORD dwLineID, dwNumDevs;
	DWORD dwAPIVersion = TAPI_CURRENT_VERSION;
	BOOL bFoundVoiceLine = FALSE;
	LPLINEDEVCAPS lpLineDevCaps = NULL;
	HLINEAPP g_hLineApp = NULL;     // Application's use handle for TAPI
	DWORD g_dwVoiceLineID = -1;   // Current line device identifier
#ifdef DEBUG
	CHAR szReport[64];
#endif

	if (g_szHWID[0] == 0)
	{
		// Initialize the application's use of Tapi.dll.
		dwRet = lineInitialize(&g_hLineApp, 
			(HINSTANCE) g_hInst, (LINECALLBACK) lineCallbackFunc, 
			_T("JetBtConfig"), &dwNumDevs);

		// If function "lineInitialize" fails, then return.
		if (dwRet)
		{
#ifdef DEBUG
			LogString("lineInitialize failed");
#endif
			return dwRet;
		}

		// If there is no device, then return.
		if (dwNumDevs == 0)
		{
#ifdef DEBUG
			LogString("There are no line devices available.");
#endif
			return LINEERR_NODEVICE;
		}

		// Find first line supporting interactive voice
		for (dwLineID = 0; dwLineID < dwNumDevs; ++dwLineID)
		{
			DWORD dwSize;
			BOOL bVoiceLine = FALSE;
			LINEEXTENSIONID extID;

#ifdef DEBUG
			sprintf(szReport, "Calling lineNegotiateAPIVersion on line %i", dwLineID);
			LogString(szReport);
#endif

			// Negotiate the API version number. If it fails, return to dwReturn.
			if (dwRet = lineNegotiateAPIVersion (
				g_hLineApp,                 // TAPI registration handle
				dwLineID,                   // Line device to be queried
				TAPI_CURRENT_VERSION,           // Least recent API version 
				TAPI_CURRENT_VERSION,       // Most recent API version 
				&dwAPIVersion,				// Negotiated API version 
				&extID))                    // Must be NULL; the provider-
			{
#ifdef DEBUG
				sprintf(szReport, "lineNegotiateAPIVersion failure %8.8X", dwRet);
				LogString(szReport);
#endif
				continue;
			}
#ifdef DEBUG
			sprintf(szReport, "lineNegotiateAPIVersion %8.8X", dwAPIVersion);
			LogString(szReport);
#endif

			dwSize = sizeof (LINEDEVCAPS);

			// Allocate enough memory for lpLineDevCaps.
			do
			{
				if (!(lpLineDevCaps = (LPLINEDEVCAPS) LocalAlloc (LPTR, dwSize)))
				{
#ifdef DEBUG
					LogString("Memory error in TAPI");
#endif
					goto LineFailed;
				}
    
				lpLineDevCaps->dwTotalSize = dwSize;
    
				if (dwRet = lineGetDevCaps(g_hLineApp, dwLineID,
					dwAPIVersion, 0, lpLineDevCaps))
				{
#ifdef DEBUG
					LogString("Couldn't get lineDevCaps");
#endif
					goto LineFailed;
				}
    
				// Stop if the allocated memory is equal to or greater than the 
				// needed memory.
				if (lpLineDevCaps->dwNeededSize <= lpLineDevCaps->dwTotalSize)
					break;
				dwSize = lpLineDevCaps->dwNeededSize;
				LocalFree (lpLineDevCaps);
				lpLineDevCaps = NULL;
    
			} while (TRUE);

			bVoiceLine = (lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE);
			if (bVoiceLine)
			{
				bFoundVoiceLine = TRUE;
				g_dwVoiceLineID = lpLineDevCaps->dwPermanentLineID;
				break;
			}

LineFailed:
#ifdef DEBUG
			LogString("This wasn't a voice line");
#endif
			; // blank line after LineFailed label
		}
		if (lpLineDevCaps)
			LocalFree (lpLineDevCaps);
		// if we found a voice line, open it and set it for notifications
		if (bFoundVoiceLine && (g_hVoiceLine == NULL))
		{
#ifdef DEBUG
			sprintf(szReport, "Found voice line ID: %i", g_dwVoiceLineID);
			LogString(szReport);
#endif
			// lineOpen
			// Open the current line.
			if (dwRet = lineOpen (
				g_hLineApp,                 // Usage handle for TAPI
				g_dwVoiceLineID,			// Cannot use the LINEMAPPER value
				&g_hVoiceLine,				// Line handle
				dwAPIVersion,				// API version number
				0,                          // Must set to zero for Windows CE
				0,                          // No data passed back 
				LINECALLPRIVILEGE_NONE,     // Can only make an outgoing call
				0,							// Media mode 
				NULL))                      // Must set to NULL for Windows CE
			{
#ifdef DEBUG
				LogString("Couldn't open voice line");
#endif
				g_hVoiceLine = NULL;
				// return dwReturn;
			}
		}
		
		if (g_hVoiceLine != NULL)
		{
			while (pInfo == NULL)
			{
				pInfo = (LPLINEGENERALINFO) LocalAlloc(LPTR, dwSize);
				if (pInfo == NULL)
				{
#ifdef DEBUG
					strcpy(szReport, "Memory error in lineGetGeneralInfo");
					LogString(szReport);
#endif
					break;
				}
				pInfo->dwTotalSize = dwSize;
				dwRet = lineGetGeneralInfo(g_hVoiceLine, pInfo);
				if ((dwRet == LINEERR_STRUCTURETOOSMALL) || (dwSize < pInfo->dwNeededSize))
				{
					dwSize = pInfo->dwNeededSize;
					LocalFree(pInfo);
					pInfo = NULL;
				}
				else if (dwRet != 0) // any other failure
				{
#ifdef DEBUG
					sprintf(szReport, "Error %8.8X in lineGetGeneralInfo", dwRet);
					LogString(szReport);
#endif
					LocalFree(pInfo);
					pInfo = NULL;
					break;
				}
			}
		}
		// Cleanup TAPI resources
		lineClose(g_hVoiceLine);
		lineShutdown(g_hLineApp);
		if (pInfo != NULL)
		{
			TCHAR * pUniString = (TCHAR *) ((BYTE *) pInfo + pInfo->dwManufacturerOffset);
			wcsncpy(g_szMfr, pUniString, min(64,pInfo->dwManufacturerSize));
			// sprintf(g_szMfr, "%ls", pUniString);
#ifdef DEBUG
			sprintf(szReport, "Mfr = %ls, size=%i", pUniString, pInfo->dwManufacturerSize);
			LogString(szReport);
#endif
			pUniString = (TCHAR *) ((BYTE *) pInfo + pInfo->dwModelOffset);
			wcsncpy(g_szModel, pUniString, min(64,pInfo->dwModelSize));
#ifdef DEBUG
			sprintf(szReport, "Model = %ls, size=%i", pUniString, pInfo->dwModelSize);
			LogString(szReport);
#endif
			pUniString = (TCHAR *) ((BYTE *) pInfo + pInfo->dwRevisionOffset);
			wcsncpy(g_szVersion, pUniString, min(64,pInfo->dwRevisionSize));
#ifdef DEBUG
			sprintf(szReport, "Revision = %ls, size=%i", pUniString, pInfo->dwRevisionSize);
			LogString(szReport);
#endif
			pUniString = (TCHAR *) ((BYTE *) pInfo + pInfo->dwSerialNumberOffset);
			memcpy(g_szHWID, pUniString, pInfo->dwSerialNumberSize);
#ifdef DEBUG
			sprintf(szReport, "Hardware ID (IMEI)=%ls, size=%i", g_szHWID, pInfo->dwSerialNumberSize);
			LogString(szReport);
#endif
			LocalFree(pInfo);
		}
	}
	return dwRet;
}

void ReadHardwareDeviceString(TCHAR * szDeviceString, WORD wFlags)
{
#ifdef DEBUG
	CHAR szReport[64];
#endif

	if (wFlags & (HWINFO_MFR | HWINFO_MODEL | HWINFO_VER))
	{
		if (GetPhoneInfo() == 0)
		{
			if ((wFlags & HWINFO_MFR) && (g_szMfr[0] != 0))
			{
				if (*szDeviceString != 0)
					lstrcat(szDeviceString, _T(" "));
				lstrcat(szDeviceString, g_szMfr);
			}
			if ((wFlags & HWINFO_MODEL) && (g_szModel[0] != 0))
			{
				if (*szDeviceString != 0)
					lstrcat(szDeviceString, _T(" "));
				lstrcat(szDeviceString, g_szModel);
			}
			if ((wFlags & HWINFO_VER) && (g_szVersion[0] != 0))
			{
				if (*szDeviceString != 0)
					lstrcat(szDeviceString, _T(" "));
				lstrcat(szDeviceString, g_szVersion);
			}
		}
	}
	else if (wFlags & HWINFO_OEM)
	{
		TCHAR szOemString[MAX_PATH];
		BOOL bRet = SystemParametersInfo(SPI_GETOEMINFO, MAX_PATH, szOemString, 0);
		if (bRet)
		{
			wcsncpy(szDeviceString, szOemString, MAX_PATH);
		}
	}
#ifdef DEBUG
	sprintf(szReport, "Device string=%S", szDeviceString);
	LogString(szReport);
#endif
	return;
}

// Purpose: Determine at runtime if the app is running on a smartphone device
static BOOL IsSmartphone() 
{
    TCHAR tszPlatform[64];

    if (TRUE == SystemParametersInfo(SPI_GETPLATFORMTYPE,
         sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
    {
        if (0 == _tcsicmp(TEXT("Smartphone"), tszPlatform)) 
        {
            return TRUE;
        }
    }
    return FALSE;   
}

static LPCTSTR StringFromResources(
    UINT uStringID
    )
{
    // NOTE: Passing NULL for the 3rd parameter of LoadString causes it to
    // return a pointer to the string in the resource file. It requires that
    // the resource file is compiled with the "/n" switch (see SDK docs).
    return (LPCTSTR) LoadString(g_hInst, uStringID, NULL, 0);
}

BOOL InitializeOutlook()
{
	// if it's already initialized, just return
	if (g_polApp != NULL)
		return TRUE;
	// otherwise initialize COM
	if (SUCCEEDED(CoInitializeEx( NULL, 0)))
	{
		// Now, let's get the main outlook application
		if (SUCCEEDED(CoCreateInstance(CLSID_Application, NULL, CLSCTX_INPROC_SERVER, 
			IID_IPOutlookApp, reinterpret_cast<void **>(&g_polApp))))
		{
			// login to the Pocket Outlook object model
			if(SUCCEEDED(g_polApp->Logon(NULL)))
			{
				IPOutlookItemCollection * pItemCol = NULL;

				if (SUCCEEDED(g_polApp->GetDefaultFolder(olFolderContacts, &g_pContactsFolder)))
				{
					IPOutlookItemCollection * pItemCol = NULL;
					if (SUCCEEDED(g_pContactsFolder->get_Items(&pItemCol)))
					{
						pItemCol->get_Count(&g_nNumContacts);
						pItemCol->Release();
						return TRUE;
					}
					// if Logon failed, cleanup POOM instance
					g_pContactsFolder->Release();
				}
			}
			g_polApp->Logoff();
			g_polApp->Release();
		}
		// and uninitialize COM
		CoUninitialize();
	}
	g_polApp = NULL;
	return FALSE;
}

void CleanupOutlook()
{
	if (g_polApp != NULL)
	{
		g_pContactsFolder->Release();
		g_polApp->Logoff();
		g_polApp->Release();
	}
	CoUninitialize();
}

int FindItemInList(LPCWSTR szFindStr)
{
	int nListCount = ListView_GetItemCount(g_hWndListView);
	int n = 0;
	int nMatchItem = -1;
	TCHAR szCurrCat[64];
#ifdef DEBUG_SORT
	CHAR szLog[128];
#endif
	for (n=0; n < nListCount; n++)
	{
		ListView_GetItemText(g_hWndListView, n, 0, szCurrCat, (64 * sizeof(TCHAR)));
		if (lstrcmp(szCurrCat, szFindStr) == 0)
		{
			nMatchItem = n;
			break;
		}
	}
#ifdef DEBUG_SORT
	sprintf(szLog, "Matched %ls at item %i", szFindStr, nMatchItem);
	LogString(szLog);
#endif
	return nMatchItem;
}

void SetSelectedCategories()
{
	/*
	*/
	TCHAR * pCurrFilterCat = g_szContactFilter;
	TCHAR   szCurCat[64];
	int nItem = 0;
	int nFilterLen = 0;

	if (g_szContactFilter == NULL)
	{
		// if no categories and IncludeNoCat=0 then no filter
		if (g_bIncludeNoCat)
		{
			nFilterLen = wcslen(szNoCat);
			wcsncpy(szCurCat, szNoCat, min(64, nFilterLen));
			szCurCat[nFilterLen] = 0;
			nItem = FindItemInList(szCurCat);
			if (nItem != -1)
			{
				ListView_SetCheckState(g_hWndListView, nItem, TRUE);
			}
		}
		else
			ListView_SetCheckState(g_hWndListView, -1, TRUE);
	}
	else
	{
		// loop through each category in the filter list
		TCHAR * pDelim = wcschr(pCurrFilterCat, ',');

		if (g_bIncludeNoCat)
		{
			nFilterLen = wcslen(szNoCat);
			wcsncpy(szCurCat, szNoCat, min(64, nFilterLen));
			szCurCat[nFilterLen] = 0;
			nItem = FindItemInList(szCurCat);
			if (nItem != -1)
			{
				ListView_SetCheckState(g_hWndListView, nItem, TRUE);
			}
		}

		while(TRUE)
		{
			nFilterLen = (pDelim != NULL) ? ((pDelim - pCurrFilterCat)) : wcslen(pCurrFilterCat);
			wcsncpy(szCurCat, pCurrFilterCat, min(64, nFilterLen));
			szCurCat[nFilterLen] = 0;
			nItem = FindItemInList(szCurCat);
			if (nItem != -1)
			{
				ListView_SetCheckState(g_hWndListView, nItem, TRUE);
			}
			if (pDelim == NULL)
				break;
			pCurrFilterCat = pDelim+1;
			if (*pCurrFilterCat == ' ')
				pCurrFilterCat++;
			pDelim = wcschr(pCurrFilterCat, ',');
		}
		LocalFree(g_szContactFilter);
		g_szContactFilter = NULL;
	}
}

void WriteSelectedCategories(HWND hWnd)
{
	TCHAR szCatList[2048];
	int nListCount = ListView_GetItemCount(g_hWndListView);
	int nSelCount = 0;
	TCHAR szCurrCat[64];
	g_bIncludeNoCat = FALSE;
#ifdef DEBUG
	CHAR szLog[2048];
#endif

	if (g_szContactFilter != NULL)
	{
		LocalFree(g_szContactFilter);
	}
	szCatList[0] = 0;
	for (int n=0; n < nListCount; n++)
	{
		if (ListView_GetCheckState(g_hWndListView, n))
		{
			nSelCount++;
			ListView_GetItemText(g_hWndListView, n, 0, szCurrCat, (64 * sizeof(TCHAR)));
			if (lstrcmp(szCurrCat, szNoCat) == 0)
			{
				g_bIncludeNoCat = TRUE;
				continue;
			}
			if (szCatList[0] != 0)
				wcscat(szCatList, _T(","));
			wcscat(szCatList, szCurrCat);
		}
	}
#ifdef DEBUG
	sprintf(szLog, "Setting filter to %ls, include (none)=%i", szCatList, g_bIncludeNoCat);
	LogString(szLog);
#endif
	if (nSelCount >= nListCount)
	{
		// If everything is selected, clear registry settings
		g_bIncludeNoCat = FALSE;
		WriteCategories(NULL);
	}
	else
	{
		WriteCategories(szCatList);
	}
}

void ReadCategories()
{
#ifdef DEBUG_SORT
	CHAR szLog[256];
#endif
	if (InitializeOutlook())
	{
		int nNumberCount = 0;
		int nCurrOlRecord = 1;
		// Open the Contacts folder
		IPOutlookItemCollection * pItemCol = NULL;

		if (SUCCEEDED(g_pContactsFolder->get_Items(&pItemCol)))
		{
			IContact * pContact = NULL;
			
			while (nCurrOlRecord <= g_nNumContacts)
			{
				if (SUCCEEDED(pItemCol->Item (nCurrOlRecord, reinterpret_cast<IDispatch**>(&pContact))))
				{
					BSTR bstrCategories;
					TCHAR * pCurrCat = NULL;
					TCHAR szMarkers[] = {',',';',0};
					// LVFINDINFO lvfi;
					LVITEM lvi;
					TCHAR szCurCat[64];
				
					// grab properties
					pContact->get_Categories(&bstrCategories);

					// run through the categories for this contact
					pCurrCat = _tcstok(bstrCategories, szMarkers);

					lvi.mask = LVIF_TEXT;
					lvi.iItem = 0;
					lvi.iSubItem = 0;
					lvi.pszText = szCurCat;
					lvi.cchTextMax = 64;

					while (pCurrCat != NULL)
					{
						if (*pCurrCat == _T(' '))
							pCurrCat++;
						// loop through each category in the filter list
						int nCatLen = wcslen(pCurrCat);

						wcsncpy(szCurCat, pCurrCat, min(64, nCatLen));
						szCurCat[nCatLen] = 0;
#ifdef DEBUG_SORT
						sprintf(szLog, "Checking for category %ls", szCurCat);
						LogString(szLog);
#endif
						if (FindItemInList(szCurCat) == -1)
						{
#ifdef DEBUG_SORT
							sprintf(szLog, "Adding category %ls", szCurCat);
							LogString(szLog);
#endif
							ListView_InsertItem(g_hWndListView, &lvi);
						}
						pCurrCat = _tcstok(NULL, szMarkers);
					}
					// clean up
					SysFreeString(bstrCategories);
					pContact->Release();
				}
				nCurrOlRecord++;
			}
			pItemCol->Release();
		}
	}
}

//Listbox management functions
BOOL InitList(
    HWND hWndParent
    )
{
	LVCOLUMN lvc;
	RECT rc;
	HDC hdc = GetDC(hWndParent);
	HFONT hBaseFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
	LOGFONT lf;

	// Build and select the font
	memset(&lf, 0, sizeof(LOGFONT));
	GetObject(hBaseFont, sizeof(lf), (LOGFONT*)&lf);

	ReleaseDC(hWndParent, hdc);

    // Create ListView and configure it
	GetClientRect(hWndParent, &rc);
	// make room for title header
	rc.top = rc.top + abs((int)(lf.lfHeight*1.5)) + 3;
	rc.bottom = rc.bottom - rc.top;
#ifdef DEBUG
	CHAR szLog[128];
	sprintf(szLog, "ListView client rect= %i,%i,%i,%i", rc.top, rc.left, rc.bottom, rc.right);
	LogString(szLog);
#endif
	
    g_hWndListView = CreateWindow(WC_LISTVIEW, TEXT("ListItem"), 
	    WS_CHILD | LVS_REPORT | LVS_SORTASCENDING | WS_VISIBLE | WS_HSCROLL | LVS_SINGLESEL | LVS_NOCOLUMNHEADER, 
	    rc.left, rc.top, rc.right, rc.bottom, hWndParent, NULL, g_hInst, NULL); 
    if (NULL == g_hWndListView)
    {
#ifdef DEBUG
		LogString("InitList CreateWindow failed");
#endif
        return FALSE;
    }
    ListView_SetExtendedListViewStyle(g_hWndListView, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
	
    // Now setup the ListView headers
    ZeroMemory(&lvc, sizeof(lvc));
	lvc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
	lvc.cx = (rc.right - rc.left) - 8;
	
	// Add column
	lvc.pszText = (LPTSTR)StringFromResources(IDS_CATEGORY);
	ListView_InsertColumn(g_hWndListView, lvc.iSubItem, &lvc);

	SetCursor(LoadCursor(NULL, IDC_WAIT));
	ReadCategories();

	{
		LVITEM lvi;
	
		lvi.mask = LVIF_TEXT;
		lvi.iItem = 0;
		lvi.iSubItem = 0;
		lvi.pszText = szNoCat;
		lvi.cchTextMax = 64;

		ListView_InsertItem(g_hWndListView, &lvi);
	}

	// GetRegSettings();
	SetSelectedCategories();
	SetCursor(NULL);
    ListView_SetItemState(g_hWndListView, 0,
        LVIS_SELECTED | LVIS_FOCUSED , LVIS_SELECTED | LVIS_FOCUSED);
    BringWindowToTop(g_hWndListView);
    SetFocus(g_hWndListView);
	
    return TRUE;
}

// populate list of message stores
BOOL GetMsgStoreList(HWND hListbox)
{
	BOOL bRet = FALSE;
	{
		IMAPISession  *   pSession    =   NULL;
		LPMAPIFOLDER        pfldrInbox  =   NULL;

		HRESULT             hr = S_OK;
		IMAPITable      *   pTable      =   NULL;
		SRowSet         *   psrs        =   NULL;
		IMsgStore       *   pStore      =   NULL;
		ULONG               rgTags[]    =   { 1, PR_RESOURCE_FLAGS };
  
		ULONG               cValues     =   0;
		LPSRowSet			pRows		=	NULL;

		ULONG				ulInboxIDn	=	0;
		LPENTRYID			pInboxID	=	NULL;
#ifdef DEBUG
		CHAR szLog[64];
#endif

		SizedSPropTagArray(3, Columns) =
		{
			3, {PR_DISPLAY_NAME, PR_RESOURCE_FLAGS, PR_ENTRYID}
		};

		hr = MAPIInitialize(NULL);
#ifdef DEBUG
		sprintf(szLog, "MAPIInitialize returned 0x%8.8X", hr);
		LogString(szLog);
#endif
		if (SUCCEEDED(hr))
		{
			// First logon to the store.
			hr = MAPILogonEx(NULL, NULL, NULL, NULL, (LPMAPISESSION *) &pSession);
#ifdef DEBUG
			sprintf(szLog, "MAPILogonEx returned 0x%8.8X", hr);
			LogString(szLog);
#endif
			if (SUCCEEDED(hr))
			{
				// Get the message stores table
				hr = pSession->GetMsgStoresTable(MAPI_UNICODE, &pTable);
#ifdef DEBUG
				sprintf(szLog, "GetMsgStoresTable returned 0x%8.8X", hr);
				LogString(szLog);
#endif
				if (SUCCEEDED(hr))
				{
					hr = pTable->SetColumns((LPSPropTagArray)&Columns, NULL);
#ifdef DEBUG
					sprintf(szLog, "SetColumns returned 0x%8.8X", hr);
					LogString(szLog);
#endif
					if (SUCCEEDED(hr))
					{
						if (SUCCEEDED(hr))
						{
							while(SUCCEEDED(pTable->QueryRows(1, 0, &psrs)))
							{
#ifdef DEBUG
								sprintf(szLog, "QueryRows returned %i rows", psrs->cRows);
								LogString(szLog);
#endif
								// Check number of rows returned. Since the above call only asks for one,
								// anything else means we are at the end of the table
								if (1 != psrs->cRows)
									break;
								else
								{
									// Make sure we got the props we need
									if ((psrs->aRow[0].cValues > 0)&&(PR_ENTRYID == psrs->aRow[0].lpProps[2].ulPropTag))
									{
#ifdef DEBUG
										LPSTR lpszProfileName = psrs->aRow[0].lpProps[0].Value.lpszA;
										sprintf(szLog, "Found store \"%S\"", lpszProfileName);
										LogString(szLog);
#endif
										SendMessage(hListbox, LB_ADDSTRING, 0, (LPARAM) psrs->aRow[0].lpProps[0].Value.lpszA);
									} // ENTRYID was returned
								} // Rows = 1
								if (psrs != NULL)
									FreeProws(psrs);          
								psrs = NULL;       

							} // SUCCEEDED QueryRows
						} // SUCCEEDED Restrict
					} // SUCCEEDED SetColumns
					RELEASE_OBJ(pTable);
				} // SUCCEEDED GetStatusTable
				RELEASE_OBJ(pSession);
			} // SUCCEEDED MAPILogonEx
		} // SUCCEEDED MAPIInitialize
	}
	return bRet;
}

void DrawTitleHeader(HWND hDlg, LPDRAWITEMSTRUCT lpdis)
{
	TCHAR szTitle[64];
	HBRUSH hbrBkColor;
	COLORREF crBkColor;
	COLORREF crTextColor;
	HFONT hCustomFont = 0;
	HDC hdc = lpdis->hDC;
	HFONT hBaseFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
	LOGFONT lf;

	GetWindowText(lpdis->hwndItem, szTitle, 64);
	// get system text and background colors
	crTextColor = GetSysColor(COLOR_STATICTEXT);
	crBkColor = GetSysColor(COLOR_STATIC);

	hbrBkColor = CreateSolidBrush (crBkColor);

	FillRect(hdc, &lpdis->rcItem, hbrBkColor);
	DeleteObject (hbrBkColor);
	SetBkColor(hdc, crBkColor);
	SetTextColor(hdc, crTextColor);

	// Build and select the font
	memset(&lf, 0, sizeof(LOGFONT));
	GetObject(hBaseFont, sizeof(lf), (LOGFONT*)&lf);
	lf.lfWeight = FW_BOLD;
	lf.lfHeight = (int) (lf.lfHeight*1.5);
	lf.lfWeight = 0;
	hCustomFont = CreateFontIndirect(&lf);
	SelectObject(hdc, hCustomFont) ;

	// Draw the item's text
	MoveToEx(hdc, 0, 0, NULL);
	RECT r = lpdis->rcItem;
	r.left = 5;
	int nHeight = DrawText(hdc, szTitle, _tcslen(szTitle), &r , DT_LEFT| DT_SINGLELINE |DT_TOP);
	MoveToEx(hdc, lpdis->rcItem.left, lpdis->rcItem.top + nHeight + 1, NULL);
	LineTo(hdc, lpdis->rcItem.right, lpdis->rcItem.top + nHeight + 1);

	SelectObject(hdc, hBaseFont);
	if (hCustomFont != 0)
	{
		DeleteObject(hCustomFont);
	}

	ReleaseDC(hDlg, hdc);
}

BOOL ScrollDialog(HWND hDlg, WPARAM wParam)
{
	DWORD dwOldTop = 0;
	DWORD dwTopRow = 0;		// ScrollInfo.nPos
	DWORD dwMaxRow = 0;		// ScrollInfo.nMax
	DWORD dwScreenRows = 0; // ScrollInfo.nPage
	DWORD dwRowSize = 0;	// GetWindowLong
	int nScrollUnits = 0;
	SCROLLINFO ScrollInfo;
	RECT rect;
	BOOL bScroll = FALSE;
	ScrollInfo.cbSize = sizeof(SCROLLINFO);
	ScrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
	GetScrollInfo(hDlg, SB_VERT, &ScrollInfo);
	dwOldTop = ScrollInfo.nPos;
	dwTopRow = ScrollInfo.nPos;
	dwMaxRow = ScrollInfo.nMax;
	dwScreenRows = ScrollInfo.nPage;
	dwRowSize = GetWindowLong(hDlg, GWL_USERDATA);

	switch(LOWORD(wParam))
	{
		case SB_LINEUP:
			nScrollUnits = -1;
			bScroll = TRUE;
			break;
		case SB_LINEDOWN:
			nScrollUnits = 1;
			bScroll = TRUE;
			break;
		case SB_PAGEUP:
			nScrollUnits = -((int)dwScreenRows/2);
			bScroll = TRUE;
			break;
		case SB_PAGEDOWN:
			nScrollUnits = (dwScreenRows/2);
			bScroll = TRUE;
			break;
		case SB_TOP:
			nScrollUnits = -(int) dwMaxRow;
			bScroll = TRUE;
			break;
		case SB_BOTTOM:
			nScrollUnits = dwMaxRow;
			bScroll = TRUE;
			break;
		case SB_THUMBPOSITION:
			nScrollUnits = (HIWORD(wParam) - dwTopRow);
			bScroll = TRUE;
			break;
			
		case SB_THUMBTRACK:
			break;
			
		case SB_ENDSCROLL:
			break;
	}
	if (!bScroll)
		return TRUE;

	// Check some limit conditions.
	if ((nScrollUnits < 0) &&(-nScrollUnits > (int) dwTopRow)) 
	{
		dwTopRow = 0;
	}
	else 
	{
		// Move the top row.
		dwTopRow += nScrollUnits;

		if (dwTopRow >((dwMaxRow+1) - dwScreenRows)) 
			dwTopRow = (dwMaxRow+1) - dwScreenRows;
	}

	if (dwTopRow == dwOldTop) 
	{
		return TRUE;
	}

	GetClientRect(hDlg, &rect);
	HideCaret(hDlg);

#ifdef DEBUG_SCROLL
	CHAR szLog[64];
	sprintf(szLog, "Scrolling to nPos=%i", dwTopRow);
	LogString(szLog);
#endif
	ScrollWindowEx(hDlg, 0, (dwOldTop - dwTopRow) * dwRowSize, NULL, &rect, NULL, NULL, 
		SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);

	ScrollInfo.cbSize = sizeof(SCROLLINFO);
	ScrollInfo.fMask = SIF_POS;
	ScrollInfo.nPos = dwTopRow;
	SetScrollInfo(hDlg, SB_VERT, &ScrollInfo, TRUE);

	ShowCaret(hDlg);
	return TRUE;
}

BOOL ResizeDialog(HWND hDlg, DWORD ctrlID, HWND hChild)
{
	if (ctrlID)
	{
		// Set up the scroll bars.
		DWORD dwTopRow = 0;		// ScrollInfo.nPos
		DWORD dwMaxRow = 0;		// ScrollInfo.nMax
		DWORD dwScreenRows = 0; // ScrollInfo.nPage
		DWORD dwRowSize = 0;	// GetWindowLong
		SCROLLINFO ScrollInfo;
		RECT rect;
		DWORD dwOldTop = dwTopRow;
		int nScrollUnits = 0;
		memset(&ScrollInfo, 0, sizeof(SCROLLINFO));
		ScrollInfo.cbSize = sizeof(SCROLLINFO);
		ScrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
		GetScrollInfo(hDlg, SB_VERT, &ScrollInfo);
		dwTopRow = ScrollInfo.nPos;
		dwMaxRow = GetWindowLong(GetDlgItem(hDlg, ctrlID), GWL_USERDATA);
		dwScreenRows = ScrollInfo.nPage;
		dwRowSize = GetWindowLong(hDlg, GWL_USERDATA);
#ifdef DEBUG_SCROLL
		CHAR szLog[64];
		sprintf(szLog, "Scrollinfo: Max=%i, Min=%i, Pos=%i, Page=%i, size=%i", ScrollInfo.nMax, ScrollInfo.nMin, ScrollInfo.nPos, ScrollInfo.nPage, dwRowSize);
		LogString(szLog);
#endif
		HideCaret(hDlg);
		if (dwTopRow != 0)
		{
    		ScrollWindowEx(hDlg, 0, dwTopRow * dwRowSize, NULL, &rect, NULL, NULL, 
				SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
		}
		GetClientRect(GetDlgItem(hDlg, ctrlID), &rect);
		dwRowSize = rect.bottom - rect.top;
		SetWindowLong(hDlg, GWL_USERDATA, dwRowSize);
		GetClientRect(hDlg, &rect);
		dwScreenRows = ((rect.bottom - rect.top) / dwRowSize);
		ScrollInfo.nPos = 0;
		ScrollInfo.nPage = dwScreenRows;
		ScrollInfo.nMax = dwMaxRow;
		ScrollInfo.nMin = 0;
		ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
#ifdef DEBUG_SCROLL
		sprintf(szLog, "Resetting scrollinfo: nPage=%i, nMax=%i, rowsize=%i, dlgHgt=%i", ScrollInfo.nPage, ScrollInfo.nMax, dwRowSize, rect.bottom);
		LogString(szLog);
#endif
		SetScrollInfo(hDlg, SB_VERT, &ScrollInfo, TRUE);
		ShowCaret(hDlg);
	}

	// Stretch Title header button to full width
	RECT rectHdr;
	RECT rectDlg;
	GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
	GetWindowRect(hDlg, &rectDlg);
	rectHdr.right = rectDlg.right;
#ifdef DEBUG_SCROLL
	CHAR szLog[128];
	sprintf(szLog, "ResizeDialog:Title %i,%i,%i,%i", rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom);
	LogString(szLog);
#endif
	SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
		SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
	// Resize child window if supplied
	if (hChild != NULL)
	{
		GetWindowRect(hChild, &rectHdr);
		rectHdr.right = rectDlg.right;
		rectHdr.bottom = rectDlg.bottom - rectHdr.top;
		SetWindowPos(hChild, hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
			SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
	}
	return TRUE;
}

BOOL SetupScrollbar(HWND hDlg, DWORD ctrlID, DWORD dwMax)
{
	// Set up the scroll bars.
	SCROLLINFO ScrollInfo;
	RECT rect;
	DWORD dwRowSize = 0;	// GetWindowLong
	GetClientRect(GetDlgItem(hDlg, ctrlID), &rect);
	dwRowSize = rect.bottom - rect.top;
	SetWindowLong(hDlg, GWL_USERDATA, dwRowSize);
	GetClientRect(hDlg, &rect);
	ScrollInfo.cbSize = sizeof(SCROLLINFO);
	ScrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
	ScrollInfo.nMin = 0;
	ScrollInfo.nMax = dwMax;
	ScrollInfo.nPage = (rect.bottom / dwRowSize);
	ScrollInfo.nPos = 0;
	SetWindowLong(GetDlgItem(hDlg, ctrlID), GWL_USERDATA, dwMax);
#ifdef DEBUG_SCROLL
	CHAR szLog[64];
	sprintf(szLog, "Setting scrollinfo: nPage=%i, nMax=%i, rowsize=%i, dlgHgt=%i", ScrollInfo.nPage, ScrollInfo.nMax, dwRowSize, rect.bottom);
	LogString(szLog);
#endif
	SetScrollInfo(hDlg, SB_VERT, &ScrollInfo, TRUE);

    // Initialize the shell activate info structure
    memset (&s_sai, 0, sizeof (s_sai));
    s_sai.cbSize = sizeof (s_sai);

    return TRUE;
}

BOOL ScrollToActiveControl(HWND hDlg, WPARAM wParam, WORD ctrlID, WORD offset)
{
	if (!IsSmartphone())
	{
		// in WM_COMMAND - NOTE: controls must have NOTIFY flag set
		if ((HIWORD(wParam) == BN_SETFOCUS) || (HIWORD(wParam) == EN_SETFOCUS)
			|| (HIWORD(wParam) == LBN_SETFOCUS))
		{
			DWORD dwRowSize = GetWindowLong(hDlg, GWL_USERDATA);
			HWND hWndFocus = GetDlgItem(hDlg, LOWORD(wParam));
			RECT rect;
			RECT focusRect;

			GetWindowRect(hDlg, &rect);
			GetClientRect(hWndFocus, &focusRect);
			MapWindowPoints(hWndFocus, hDlg, (LPPOINT) &focusRect, 2);
			if ((focusRect.bottom + (long) dwRowSize > rect.bottom) || (focusRect.top + (long) dwRowSize < rect.top))
				PostMessage(hDlg, WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, (LOWORD(wParam)-ctrlID+offset)), 0);
		}
	}
	return TRUE;
}


int WINAPI WinMain (
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance, 
    LPWSTR lpCmdLine, 
    int nShowCmd
    )

{
    MSG msg = {0};

    // Store the application instance in our global variable.
    g_hInst = hInstance;

#ifdef DEBUG
	CHAR szLog[128];
	sprintf(szLog, "WinMain cmdline = %ls", lpCmdLine);
	LogString(szLog);
#endif
	if (!IsRunning())
	{
		if (!IsSupported())
		{
			if (MessageBox(NULL, _T("Your phone does not support the JETware Hands-free Extension"), _T("Error"), MB_OKCANCEL) == IDOK)
				return (0);
		}
		if (CeGetCurrentTrust() != OEM_CERTIFY_TRUST)
		{
			if (MessageBox(NULL, _T("Your phone's security settings prevent this version of the JETware Hands-free Extension from loading"), _T("Error"), MB_OKCANCEL) == IDOK)
				return (0);
		}
	}
	if (lpCmdLine != NULL)
	{
		if (lstrcmp(lpCmdLine, _T("-ON")) == 0)
		{
			// Turn BT radio on
			SetCursor(LoadCursor(NULL, IDC_WAIT));
			BthSetMode(BTH_CONNECTABLE);
			SetCursor(NULL);
			return (0);
		}
		else if (lstrcmp(lpCmdLine, _T("-OFF")) == 0)
		{
			// Turn BT radio off
			BthSetMode(BTH_POWER_OFF);
			return (0);
		}
		else if (lstrcmp(lpCmdLine, _T("-TOGGLE")) == 0)
		{
			// Toggle BT radio
			DWORD dwMode = 0;
			SetCursor(LoadCursor(NULL, IDC_WAIT));
			BthGetMode(&dwMode);
			BthSetMode((dwMode == BTH_POWER_OFF) ? BTH_CONNECTABLE : BTH_POWER_OFF);
			SetCursor(NULL);
			return (0);
		}
		else if (lstrcmp(lpCmdLine, _T("-RESTART")) == 0)
		{
			BYTE Info[] = {0,0};
			DWORD BytesReturned;
			KernelIoControl(0x101003C, (LPVOID)(Info), 1, (LPVOID)(&Info[1]), 1, &BytesReturned);
			return (0);
		}
		else if (wcsncmp(lpCmdLine, _T("-IMPORT"), 7) == 0)
		{
			if(AddDeviceSettings(NULL, lpCmdLine+8))
				MessageBox(NULL, _T("Settings added successfully"), _T("Succeeded"), MB_OK | MB_SETFOREGROUND);
			else
				MessageBox(NULL, _T("Settings could not be added"), _T("Failed"), MB_OK | MB_SETFOREGROUND);
			return (0);
		}
	}

    // Load strings
    // Use a globally named mutex to detect another instance of app
    const HANDLE hMutex = CreateMutex(0, 0, TEXT("_JETBTAG_CONFIG_"));
    // check the result code
    if (hMutex != NULL) 
    {
        // No other instances running? Okay to proceed...
        if (GetLastError() != ERROR_ALREADY_EXISTS) 
        {
			INITCOMMONCONTROLSEX ics;

			ics.dwSize = sizeof(INITCOMMONCONTROLSEX);
			ics.dwICC = ICC_UPDOWN_CLASS | ICC_CAPEDIT_CLASS | ICC_LISTVIEW_CLASSES;

			InitCommonControlsEx(&ics);
			GetRegSettings();
			DialogBox(g_hInst, MAKEINTRESOURCE(IDD_MAIN), 0, (DLGPROC)MainDialogProc);
            // Fall through to Cleanup
        }
        else 
        {
#ifdef DEBUG
			LogString("switching to existing instance");
#endif
            // Already an instance running - attempt to switch to it and then exit
            const HWND hwndExistingInstance = FindWindow(_T("Dialog"), _T("Hands-Free Settings"));
            if (NULL != hwndExistingInstance) 
            {
                SetForegroundWindow((HWND)(((ULONG)hwndExistingInstance) | 0x1));
            }
        }
    }

    if (0 != hMutex) 
    {
        VERIFY(CloseHandle(hMutex));
    }
	CleanupOutlook();
	if (g_szMsgStore[MESSAGES_ME] != NULL)
		LocalFree(g_szMsgStore[MESSAGES_ME]);
	if (g_szMsgStore[MESSAGES_SM] != NULL)
		LocalFree(g_szMsgStore[MESSAGES_SM]);
	if (g_szMsgStoreNew[MESSAGES_ME] != NULL)
		LocalFree(g_szMsgStoreNew[MESSAGES_ME]);
	if (g_szMsgStoreNew[MESSAGES_SM] != NULL)
		LocalFree(g_szMsgStoreNew[MESSAGES_SM]);
	if (g_szContactFilter != NULL)
		LocalFree(g_szContactFilter);


    return msg.wParam;
}

BOOL CALLBACK MainDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;
    switch(uiMessage)
    {
		case WM_KEYUP:
		{
#ifdef DEBUG
			CHAR szLog[128];
			sprintf(szLog, "Keyboard message %4.4X, key=%4.4X, data=%8.8X", uiMessage, wParam, lParam);
			LogString(szLog);
#endif
			if ((wParam == VK_RETURN) || (wParam == 'D') || (wParam == 'd'))
			{
				if (!IsSmartphone() && (wParam == VK_RETURN))
					break;
				// Launch troubleshooting dialog
				if (g_wDebugLevels == 0)
				{
					if (MessageBox(hDlg, _T("Do you want to enable diagnostic logging of the JETware Hands-free Extension?"), _T("Logs disabled"), MB_YESNO) == IDYES)
						SetLogging(0xFFFF);
				}
				else
				{
					if (MessageBox(hDlg, _T("Do you want to disable diagnostic logging of the JETware Hands-free Extension?"), _T("Logs enabled"), MB_YESNO) == IDYES)
						SetLogging(0);
				}
			}
			if ((wParam == 'R') || (wParam == 'r'))
			{
				// Restart JETware service
				if (MessageBox(hDlg, _T("Do you want to restart the JETware Hands-free Extension?"), _T("Restart JETware Extensions"), MB_YESNO) == IDYES)
				{
					RestartJPB();
					RestartBAG();
				}
			}
			break;
		}
        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
			mbi.nToolBarId  = IDR_MENUBAR;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }
			memset(g_szModel, 0, sizeof(g_szModel));
			memset(g_szMfr, 0, sizeof(g_szMfr));
			memset(g_szVersion, 0, sizeof(g_szVersion));
			memset(g_szHWID, 0, sizeof(g_szHWID));
			// Override the BACK key so we can send it to the edit control
			// SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TTALK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
			HMENU hSK2Menu = (HMENU)SendMessage(mbi.hwndMB, SHCMBM_GETSUBMENU, 0, IDM_MENU);

			GetRegSettings();
			// Check to see if module is in use
			if (IsRunning())
			{
				// Couldn't open module exclusively, so must be in use
				SetDlgItemText(hDlg, IDC_STATUS, _T("Extension is active."));
			}
			else
			{
				SetDlgItemText(hDlg, IDC_STATUS, _T("Extension is not currently active."));
				if (IsRegistered())
				{
					if (IsInstalled())
					{
						if (MessageBox(hDlg, _T("Extension is not loaded, would you like to load it now?"), _T("Notice"), MB_YESNO) == IDYES)
						{
							// stop and start btagsvc.dll service
							SetCursor(LoadCursor(NULL, IDC_WAIT));
							BOOL bLoaded = RestartBAG();
							SetCursor(NULL);
							if (bLoaded)
							{
								SetDlgItemText(hDlg, IDC_STATUS, _T("Extension is active."));
							}
							else
							{
								MessageBox(hDlg, _T("Unable to load JETware Hands-free Extension. Your phone may not support this version of the extension."), _T("Error"), MB_OK);
							}
						}
					}
					else
						MessageBox(hDlg, _T("JETware Hands-free Extension must be reinstalled"), _T("File not found"), MB_OK);
				}
				else
				{
					if (IsInstalled())
					{
						if (MessageBox(hDlg, _T("Extension is not registered, would you like to register it now?"), _T("Notice"), MB_YESNO) == IDYES)
						{
							BOOL bSuccess = FALSE;
							// Register it
							if (Register())
							{
								if (MessageBox(hDlg, _T("Extension is not loaded, would you like to load it now?"), _T("Notice"), MB_YESNO) == IDYES)
								{
									// stop and start btagsvc.dll service
									SetCursor(LoadCursor(NULL, IDC_WAIT));
									BOOL bLoaded = RestartBAG();
									SetCursor(NULL);
									if (bLoaded)
									{
										bSuccess = TRUE;
										SetDlgItemText(hDlg, IDC_STATUS, _T("Extension is active."));
									}
								}
							}
							if (!bSuccess)
							{
								MessageBox(hDlg, _T("Unable to load JETware Hands-free Extension. Your phone may not support this version of the extension."), _T("Error"), MB_OK);
							}
						}
					}
					else
						MessageBox(hDlg, _T("JETware Hands-free Extension must be reinstalled"), _T("File not found"), MB_OK);
				}
			}
			SetDlgItemText(hDlg, IDC_TEXT, _T("This is the open source version of the JETware Hands-free Extension. Use the menu options to configure settings."));

			// Check to see if shortcuts have already been created
			TCHAR szStartMenu[MAX_PATH];
			BOOL bRet = SHGetSpecialFolderPath(hDlg, szStartMenu, CSIDL_STARTMENU, FALSE);
			if (!IsSmartphone())
			{
				bRet = SHGetSpecialFolderPath(hDlg, szStartMenu, CSIDL_PROGRAMS, FALSE);
			}
			lstrcat(szStartMenu, L"\\Bluetooth Options\\Toggle Bluetooth.lnk");
			DWORD dwAttr = GetFileAttributes(szStartMenu);
			if (dwAttr != 0xFFFFFFFF)
			{
				EnableMenuItem(hSK2Menu, ID_SHORTCUTS, MF_GRAYED);
			}

			SetupScrollbar(hDlg, IDC_ENABLE_BT, 9);

			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
            break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
		case WM_SIZE:
			ResizeDialog(hDlg, IDC_ENABLE_BT, NULL);
			break;
 		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            {
				case IDC_ENABLE_BT:
					SetCursor(LoadCursor(NULL, IDC_WAIT));
					BthSetMode((IsDlgButtonChecked(hDlg, IDC_ENABLE_BT)) ? BTH_CONNECTABLE : BTH_POWER_OFF);
					SetCursor(NULL);
					break;
				case IDC_RESTART:
					{
						BYTE Info[] = {0,0};
						DWORD BytesReturned;
						KernelIoControl(0x101003C, (LPVOID)(Info), 1, (LPVOID)(&Info[1]), 1, &BytesReturned);
						break;
					}
				case IDM_ABOUT:
					DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hDlg, (DLGPROC)AboutDialogProc);
					// hActiveChild = NULL;
					break;
				case IDM_PHONEBOOK:
					GetRegSettings();
					DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CATEGORIES), hDlg, (DLGPROC)CategoriesDialogProc);
					// hActiveChild = NULL;
					break;
				case IDM_MESSAGING:
					GetRegSettings();
					DialogBox(g_hInst, MAKEINTRESOURCE(IDD_MESSAGING), hDlg, (DLGPROC)MessagingDialogProc);
					// hActiveChild = NULL;
					break;
				case IDM_FEATURES:
					GetRegSettings();
					MessageBox(hDlg, _T("Changing these settings may prevent some features from working properly"), _T("Warning"), MB_OK);
					DialogBox(g_hInst, MAKEINTRESOURCE(IDD_FEATURES), hDlg, (DLGPROC)FeaturesDialogProc);
					// hActiveChild = NULL;
					break;
				case IDM_REGISTER:
					GetRegSettings();
					DialogBox(g_hInst, MAKEINTRESOURCE(IDD_REGISTER), hDlg, (DLGPROC)RegisterDialogProc);
					// hActiveChild = NULL;
					break;
				case ID_SHORTCUTS:
					{
						TCHAR szCmdLine[256];
						TCHAR szLinkPath[256];
						TCHAR szStartMenu[MAX_PATH];
						TCHAR szPath[MAX_PATH];
						// HMODULE hMod = NULL;
						DWORD dwRet;

						BOOL bRet = SHGetSpecialFolderPath(hDlg, szStartMenu, CSIDL_STARTMENU, FALSE);
						if (!IsSmartphone())
						{
							bRet = SHGetSpecialFolderPath(hDlg, szStartMenu, CSIDL_PROGRAMS, FALSE);
						}
						lstrcat(szStartMenu, L"\\Bluetooth Options");

						dwRet = GetModuleFileName(NULL, szPath, MAX_PATH);

						if (!dwRet)
						{
							bRet = SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAM_FILES, FALSE);
							lstrcat(szPath, L"\\JETware\\JetBTConfig.exe");
						}

						wsprintf(szCmdLine, _T("\"%s\" -ON?%s,-%i"), szPath, szPath, IDI_ON);
						wsprintf(szLinkPath, _T("%s\\Turn on Bluetooth.lnk"), szStartMenu);
						bRet = SHCreateShortcut(szLinkPath, szCmdLine);

						wsprintf(szCmdLine, _T("\"%s\" -OFF?%s,-%i"), szPath, szPath, IDI_OFF);
						wsprintf(szLinkPath, _T("%s\\Turn off Bluetooth.lnk"), szStartMenu);
						bRet = SHCreateShortcut(szLinkPath, szCmdLine);

						wsprintf(szCmdLine, _T("\"%s\" -TOGGLE?%s,-%i"), szPath, szPath, IDI_TOGGLE);
						wsprintf(szLinkPath, _T("%s\\Toggle Bluetooth.lnk"), szStartMenu);
						bRet = SHCreateShortcut(szLinkPath, szCmdLine);
						if (bRet)
							wsprintf(szCmdLine, _T("Shortcuts created in %s"), szStartMenu);
						else
							wsprintf(szCmdLine, _T("Error creating shortcuts in %s"), szStartMenu);
						MessageBox(hDlg, szCmdLine, _T("Finished"), MB_OK);

						HMENU hSK2Menu = (HMENU)SendMessage(SHFindMenuBar(hDlg), SHCMBM_GETSUBMENU, 0, IDM_MENU);
						EnableMenuItem(hSK2Menu, ID_SHORTCUTS, MF_GRAYED);
						break;
					}
				case IDOK:
					if (IsSmartphone())
					{
						// We don't want the action key on an edit control to dismiss the dialog
						bProcessedMsg = false;
						break;
					}
					// else intentionally fall through on PocketPC
                case ID_DONE:
                case IDCANCEL:
					// if (g_wSLA < SLA_EVALUATION)
					//	ShowExpiredMessage(hDlg);
                    EndDialog(hDlg, 0);
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
			{
				DWORD dwBTMode = 0;
				BthGetMode(&dwBTMode);
				CheckDlgButton(hDlg, IDC_ENABLE_BT, (dwBTMode != BTH_POWER_OFF) ? BST_CHECKED : BST_UNCHECKED);
			}
			break;
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

#define SZ_OPEN _T("Open")

BOOL CALLBACK RegisterDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
            break;

        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
			mbi.nToolBarId  = IDR_REG_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }
			// Override the BACK key so we can send it to the edit control
			SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
			TCHAR szTitle[64];

			GetWindowText(GetParent(hDlg), szTitle, 64);
			SetWindowText(hDlg, szTitle);

			GetRegSettings();
			SetDlgItemText(hDlg, IDC_PHONEID, g_szIMEI);
			SetDlgItemText(hDlg, IDC_ACTCODE, _T("Open source"));
			EnableWindow(GetDlgItem(hDlg, IDC_ACTCODE), FALSE);
			SetDlgItemText(hDlg, IDC_REG_MESSAGE, _T("Open source version of JETware Hands-Free Extension"));

			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);

			// hActiveChild = hDlg;
			SetupScrollbar(hDlg, IDC_PHONEID, 11);
            break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
		case WM_SIZE:
			ResizeDialog(hDlg, IDC_PHONEID, NULL);
			break;
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            {
				case IDOK:
					if (IsSmartphone())
					{
						// We don't want the action key on an edit control to dismiss the dialog
						bProcessedMsg = false;
						break;
					}
					// else intentionally fall through on PocketPC
                case ID_DONE:
                case IDCANCEL:
                    EndDialog(hDlg, 0);
					// hActiveChild = NULL;
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
        
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

BOOL CALLBACK PhonebookDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
		case WM_SIZE:
			ResizeDialog(hDlg, IDC_MAX_ME, NULL);
			break;
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
            break;

        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
            mbi.nToolBarId  = IDR_DIALOG_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }
			// Override the BACK key so we can send it to the edit control
			SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
			TCHAR szTitle[64];

			GetWindowText(GetParent(hDlg), szTitle, 64);
			SetWindowText(hDlg, szTitle);

			if (!g_dwIncludeFax)
			{
				CheckDlgButton(hDlg, IDC_INCLUDE_FAX, BST_CHECKED);
			}
			if ((g_dwMaxContacts[CONTACTS_ME] != NO_LIMIT) || (g_dwMaxContacts[CONTACTS_SM] != NO_LIMIT) ||
				(g_dwMaxContacts[CONTACTS_DC] != NO_LIMIT) || (g_dwMaxContacts[CONTACTS_RC] != NO_LIMIT) || 
				(g_dwMaxContacts[CONTACTS_MC] != NO_LIMIT))
			{
				// TODO: Blank = NO_LIMIT
				CheckDlgButton(hDlg, IDC_LIMIT_PB, BST_CHECKED);
				if (g_dwMaxContacts[CONTACTS_ME] != NO_LIMIT)
					SetDlgItemInt(hDlg, IDC_MAX_ME, g_dwMaxContacts[CONTACTS_ME], 0);
				EnableWindow(GetDlgItem(hDlg, IDC_MAX_ME), TRUE);
				EnableWindow(GetDlgItem(hDlg, IDC_TEXT_ME), TRUE);

				if (g_dwMaxContacts[CONTACTS_SM] != NO_LIMIT)
					SetDlgItemInt(hDlg, IDC_MAX_SM, g_dwMaxContacts[CONTACTS_SM], 0);
				EnableWindow(GetDlgItem(hDlg, IDC_MAX_SM), TRUE);
				EnableWindow(GetDlgItem(hDlg, IDC_TEXT_SM), TRUE);

				if (g_dwMaxContacts[CONTACTS_DC] != NO_LIMIT)
					SetDlgItemInt(hDlg, IDC_MAX_DC, g_dwMaxContacts[CONTACTS_DC], 0);
				EnableWindow(GetDlgItem(hDlg, IDC_MAX_DC), TRUE);
				EnableWindow(GetDlgItem(hDlg, IDC_TEXT_DC), TRUE);

				if (g_dwMaxContacts[CONTACTS_RC] != NO_LIMIT)
					SetDlgItemInt(hDlg, IDC_MAX_RC, g_dwMaxContacts[CONTACTS_RC], 0);
				EnableWindow(GetDlgItem(hDlg, IDC_MAX_RC), TRUE);
				EnableWindow(GetDlgItem(hDlg, IDC_TEXT_RC), TRUE);

				if (g_dwMaxContacts[CONTACTS_MC] != NO_LIMIT)
					SetDlgItemInt(hDlg, IDC_MAX_MC, g_dwMaxContacts[CONTACTS_MC], 0);
				EnableWindow(GetDlgItem(hDlg, IDC_MAX_MC), TRUE);
				EnableWindow(GetDlgItem(hDlg, IDC_TEXT_MC), TRUE);
			}
			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);

			SetupScrollbar(hDlg, IDC_MAX_ME, 10);
			break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
        case WM_COMMAND:
			ScrollToActiveControl(hDlg, wParam, IDC_INCLUDE_FAX, 1);
            switch (LOWORD(wParam)) 
            {
				case IDC_LIMIT_PB:
				{
					EnableWindow(GetDlgItem(hDlg, IDC_MAX_ME), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_TEXT_ME), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_MAX_SM), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_TEXT_SM), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_MAX_DC), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_TEXT_DC), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_MAX_RC), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_TEXT_RC), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_MAX_MC), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					EnableWindow(GetDlgItem(hDlg, IDC_TEXT_MC), IsDlgButtonChecked(hDlg, IDC_LIMIT_PB));
					break;
				}
				case IDOK:
					if (IsSmartphone())
					{
						bProcessedMsg = false;
						break;
					}
					// else intentionally fall through on PocketPC
                case ID_DONE:
				{
					if (IsDlgButtonChecked(hDlg, IDC_LIMIT_PB))
					{
						BOOL bSet = FALSE;
						g_dwMaxContacts[CONTACTS_ME] = GetDlgItemInt(hDlg, IDC_MAX_ME, &bSet, FALSE);
						if (!bSet)
							g_dwMaxContacts[CONTACTS_ME] = NO_LIMIT;

						g_dwMaxContacts[CONTACTS_SM] = GetDlgItemInt(hDlg, IDC_MAX_SM, &bSet, FALSE);
						if (!bSet)
							g_dwMaxContacts[CONTACTS_SM] = NO_LIMIT;

						g_dwMaxContacts[CONTACTS_DC] = GetDlgItemInt(hDlg, IDC_MAX_DC, &bSet, FALSE);
						if (!bSet)
							g_dwMaxContacts[CONTACTS_DC] = NO_LIMIT;

						g_dwMaxContacts[CONTACTS_RC] = GetDlgItemInt(hDlg, IDC_MAX_RC, &bSet, FALSE);
						if (!bSet)
							g_dwMaxContacts[CONTACTS_RC] = NO_LIMIT;

						g_dwMaxContacts[CONTACTS_MC] = GetDlgItemInt(hDlg, IDC_MAX_MC, &bSet, FALSE);
						if (!bSet)
							g_dwMaxContacts[CONTACTS_MC] = NO_LIMIT;
					}
					else
					{
						g_dwMaxContacts[CONTACTS_ME] = NO_LIMIT;
						g_dwMaxContacts[CONTACTS_SM] = NO_LIMIT;
						g_dwMaxContacts[CONTACTS_DC] = NO_LIMIT;
						g_dwMaxContacts[CONTACTS_RC] = NO_LIMIT;
						g_dwMaxContacts[CONTACTS_MC] = NO_LIMIT;
					}
					g_dwIncludeFax = !IsDlgButtonChecked(hDlg, IDC_INCLUDE_FAX);
					WriteAdvancedSettings();
					// if (g_wSLA < SLA_EVALUATION)
					//	ShowExpiredMessage(hDlg);
				}
                case IDCANCEL:
                    EndDialog(hDlg, 0);
					// hActiveGrandchild = NULL;
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
        
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

BOOL CALLBACK MessagingDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
            break;
		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
		case WM_SIZE:
			ResizeDialog(hDlg, IDC_INCLUDE_READ1, NULL);
			break;
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
            mbi.nToolBarId  = IDR_DIALOG_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }
			// Override the BACK key so we can send it to the edit control
			SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
			TCHAR szTitle[64];

			GetWindowText(GetParent(hDlg), szTitle, 64);
			SetWindowText(hDlg, szTitle);

			// Populate settings into controls
			CheckDlgButton(hDlg, IDC_INCLUDE_READ1, (g_bAllMsgs[MESSAGES_ME]) ? BST_CHECKED : BST_UNCHECKED);
			CheckDlgButton(hDlg, IDC_INCLUDE_UNREAD1, BST_CHECKED);
			SetDlgItemInt(hDlg, IDC_MAX_MESSAGES1, g_dwMsgMax[MESSAGES_ME], 0);
			GetMsgStoreList(GetDlgItem(hDlg, IDC_PROV_LIST1));
			SendDlgItemMessage(hDlg, IDC_PROV_LIST1, LB_SELECTSTRING, -1, (LPARAM) g_szMsgStore[MESSAGES_ME]);
			
			CheckDlgButton(hDlg, IDC_INCLUDE_READ2, (g_bAllMsgs[MESSAGES_SM]) ? BST_CHECKED : BST_UNCHECKED);
			CheckDlgButton(hDlg, IDC_INCLUDE_UNREAD2, BST_CHECKED);
			SetDlgItemInt(hDlg, IDC_MAX_MESSAGES2, g_dwMsgMax[MESSAGES_SM], 0);
			GetMsgStoreList(GetDlgItem(hDlg, IDC_PROV_LIST2));
			SendDlgItemMessage(hDlg, IDC_PROV_LIST2, LB_SELECTSTRING, -1, (LPARAM) g_szMsgStore[MESSAGES_SM]);

			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);

			SetupScrollbar(hDlg, IDC_INCLUDE_READ1, 11);
			break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
        case WM_COMMAND:
			ScrollToActiveControl(hDlg, wParam, IDC_PROV_LIST1, 2);
            switch (LOWORD(wParam)) 
            {

				case IDOK:
					if (IsSmartphone())
					{
						bProcessedMsg = false;
						break;
					}
					// else intentionally fall through on PocketPC
                case ID_DONE:
				{
					TCHAR szProvider[64];
					DWORD dwLen = 0;
					g_bAllMsgsNew[MESSAGES_ME] = IsDlgButtonChecked(hDlg, IDC_INCLUDE_READ1);
					g_dwMsgMaxNew[MESSAGES_ME] = GetDlgItemInt(hDlg, IDC_MAX_MESSAGES1, NULL, FALSE);
					// GetDlgItemText(hDlg, IDC_PROV_LIST1, szProvider, 64);
					SendDlgItemMessage(hDlg, IDC_PROV_LIST1, LB_GETTEXT,
						SendDlgItemMessage(hDlg, IDC_PROV_LIST1, LB_GETCURSEL, 0, 0), (LPARAM) szProvider);
					if (lstrcmp(szProvider, g_szMsgStoreNew[MESSAGES_ME]) != 0)
					{ // This provider has changed
#ifdef DEBUG
						CHAR szLog[256];
						sprintf(szLog, "Mail1 Prov=%ls, Old=%ls, new=%ls", szProvider, g_szMsgStore[MESSAGES_ME], g_szMsgStoreNew[MESSAGES_ME]);
						LogString(szLog);
#endif
						dwLen = (lstrlen(szProvider)+1) * sizeof(TCHAR);
						if (g_szMsgStoreNew[MESSAGES_ME] != NULL)
						{
							LocalFree(g_szMsgStoreNew[MESSAGES_ME]);
							g_szMsgStoreNew[MESSAGES_ME] = NULL;
						}
						g_szMsgStoreNew[MESSAGES_ME] = (TCHAR *)LocalAlloc(LPTR, dwLen);
						lstrcpy(g_szMsgStoreNew[MESSAGES_ME], szProvider);
					}
					g_bAllMsgsNew[MESSAGES_SM] = IsDlgButtonChecked(hDlg, IDC_INCLUDE_READ2);
					g_dwMsgMaxNew[MESSAGES_SM] = GetDlgItemInt(hDlg, IDC_MAX_MESSAGES2, NULL, FALSE);
					SendDlgItemMessage(hDlg, IDC_PROV_LIST2, LB_GETTEXT,
						SendDlgItemMessage(hDlg, IDC_PROV_LIST2, LB_GETCURSEL, 0, 0), (LPARAM) szProvider);
					if (lstrcmp(szProvider, g_szMsgStoreNew[MESSAGES_SM]) != 0)
					{ // This provider has changed
#ifdef DEBUG
						CHAR szLog[256];
						sprintf(szLog, "Mail2 Prov=%ls, Old=%ls, new=%ls", szProvider, g_szMsgStore[MESSAGES_SM], g_szMsgStoreNew[MESSAGES_SM]);
						LogString(szLog);
#endif
						dwLen = (lstrlen(szProvider)+1) * sizeof(TCHAR);
						if (g_szMsgStoreNew[MESSAGES_SM] != NULL)
						{
							LocalFree(g_szMsgStoreNew[MESSAGES_SM]);
							g_szMsgStoreNew[MESSAGES_SM] = NULL;
						}
						g_szMsgStoreNew[MESSAGES_SM] = (TCHAR *)LocalAlloc(LPTR, dwLen);
						lstrcpy(g_szMsgStoreNew[MESSAGES_SM], szProvider);
					}
					WriteMessageSettings();
					// if (g_wSLA < SLA_EVALUATION)
					//	ShowExpiredMessage(hDlg);
				}
                case IDCANCEL:
                    EndDialog(hDlg, 0);
					// hActiveChild = NULL;
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
        
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

BOOL CALLBACK CategoriesDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
            break;

        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
            mbi.nToolBarId  = IDR_PB_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }
			// Override the BACK key so we can send it to the edit control
			// SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
			TCHAR szTitle[64];

			GetWindowText(GetParent(hDlg), szTitle, 64);
			SetWindowText(hDlg, szTitle);

			if (g_hWndListView == NULL)
			{
				if (FALSE == InitList(hDlg))
				{
					MessageBox(NULL, TEXT("Failed to init window"), TEXT("Hands-Free Config"), MB_OK);
					//Failed init, lets quit
					DestroyWindow(hDlg);
					PostMessage(GetParent(hDlg), WM_CLOSE, NULL, NULL);
				}
			}
			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
			// Populate settings into controls

            break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            {
				case IDM_SELECT_ALL:
				case IDM_CLEAR_ALL:
					ListView_SetCheckState(g_hWndListView, -1, (LOWORD(wParam) == IDM_SELECT_ALL));
					break;
				case IDM_LIMITS:
					GetRegSettings();
					DialogBox(g_hInst, MAKEINTRESOURCE(IDD_PHONEBOOK), hDlg, (DLGPROC)PhonebookDialogProc);
					break;
				case IDM_REFRESH:
					BringWindowToTop(g_hWndListView);
					SetFocus(g_hWndListView);
					break;
				case IDOK:
					if (IsSmartphone())
					{
						bProcessedMsg = false;
						break;
					}
					// else intentionally fall through on PocketPC
				case IDM_SENDPB:
                case ID_DONE:
					WriteSelectedCategories(hDlg);
					// if (g_wSLA < SLA_EVALUATION)
					//	ShowExpiredMessage(hDlg);
					if (LOWORD(wParam) == IDM_SENDPB)
					{
						SendSelectedContacts(hDlg);
					}
                case IDCANCEL:
					DestroyWindow(g_hWndListView);
					g_hWndListView = NULL;
                    EndDialog(hDlg, 0);
					// hActiveChild = NULL;
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
		case WM_NOTIFY:
			{
				NMHDR* pnmhdr = (NMHDR*)lParam;
				if (LVN_ITEMACTIVATE  == pnmhdr->code)
				{
					NMLISTVIEW* pnmlv = (NMLISTVIEW*)lParam;
				}
			}
			break;
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
		case WM_DESTROY:
			DestroyWindow(g_hWndListView);
			break;
		case WM_SIZE:
			// Check to see if app is being Minimized
			ResizeDialog(hDlg, 0, g_hWndListView);
			if (SIZE_MINIMIZED == wParam) 
			{
				// App being minimized we'll just close instead
				DestroyWindow(hDlg);
			}
			break;
		case WM_CREATE:
#ifdef DEBUG
			LogString("WM_CREATE");
#endif
			if (g_hWndListView == NULL)
			{
#ifdef DEBUG
				LogString("\tCREATE calling InitList");
#endif
				if (FALSE == InitList(hDlg))
				{
					MessageBox(NULL, TEXT("Failed to init window"), TEXT("Hands-Free Config"), MB_OK);
					//Failed init, lets quit
					DestroyWindow(hDlg);
					PostMessage(GetParent(hDlg), WM_CLOSE, NULL, NULL);
				}
			}
#ifdef DEBUG
			LogString("\tCREATE done");
#endif
			break;
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

BOOL CALLBACK FeaturesDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
            break;
		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
		case WM_SIZE:
			ResizeDialog(hDlg, IDC_IBRT_FEATURE, NULL);
			break;
        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags |= SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
            mbi.nToolBarId  = IDR_ADV_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }
			// Override the BACK key so we can send it to the edit control
			// SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
			TCHAR szTitle[64];

			GetWindowText(GetParent(hDlg), szTitle, 64);
			SetWindowText(hDlg, szTitle);

			// Check to see if this is a Treo, if it is, disable voice dial and in-band ringtones
			GetPhoneInfo();
			BOOL	bDisableVoice		= FALSE;
			BOOL	bVoiceAppRegistered = FALSE;
			HKEY    hKey                = NULL;
			DWORD   dwType              = 0;
			DWORD	dwSize				= 0;
			TCHAR	szPath[256];
			TCHAR	szValue[256];
			DWORD	wValue				= 0;
			LONG	lRet				= 0;
			DWORD dwMaxRow = 0;		// ScrollInfo.nMax


			WORD wFlags = HWINFO_OEM;
			while (wFlags >= HWINFO_MFR)
			{
				szValue[0] = 0;
				ReadHardwareDeviceString(szValue, wFlags);
				if (szValue[0] != 0)
				{
					wcscpy(szPath, JETWARE_KEY);
					wcscat(szPath, _T("\\"));
					wcscat(szPath, szValue);

					if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, 0, &hKey))
					{
						// read in-band ringtone support
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, IN_BAND_RING, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwInBandRing = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_IBRT_FEATURE), FALSE);
						}
						// read CMER handling
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, HANDLE_CMER, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwHandleCMER = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_MER_FEATURE), FALSE);
						}
						// read CIND handling
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, HANDLE_CIND, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwHandleCIND = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_IND_FEATURE), FALSE);
						}
						// read CLIP handling
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, HANDLE_CLIP, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwHandleCLIP = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_CID_FEATURE), FALSE);
						}
						// read CHUP handling
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, HANDLE_CHUP, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwHandleCHUP = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_CHUP_FEATURE), FALSE);
						}
						// read CKPD handling (Voice dialing)
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, HANDLE_CKPD, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwHandleCKPD = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_VA_FEATURE), FALSE);
							if (!g_dwHandleCKPD)
								bDisableVoice = TRUE;
						}
						// read CPMS handling
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, HANDLE_CPMS, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwHandleCPMS = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_MSG_FEATURE), FALSE);
						}
						// read CPBS handling
						dwSize = sizeof(DWORD);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, HANDLE_CPBS, NULL, &dwType, (LPBYTE) &wValue, &dwSize);
						if (dwSize && (dwType == REG_DWORD))
						{
							g_dwHandleCPBS = wValue;
							EnableWindow(GetDlgItem(hDlg, IDC_PB_FEATURE), FALSE);
						}

						RegCloseKey(hKey);
						break;
					}
				}
				wFlags--;
			}
/*
			if (wcscmp(g_szModel, _T("Treo 700W")) == 0)
			{
				bDisableVoice = TRUE;
			}
*/
			if (!bDisableVoice)
			{
				// Check whether voice dial app is registered

				// first check VoiceCommand key
				lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, VC_BUTTON_KEY, 0, 0, &hKey);
				if (ERROR_SUCCESS == lRet)
				{
					// Attempt to launch Voice Command if it is installed
					// For VC 1.6 call voicecmd.exe -BTHPTT
					// read executable path
					dwSize = sizeof(szPath);
					dwType = 0;
					lRet = RegQueryValueEx(hKey, VC_PATH, NULL, &dwType, (LPBYTE) &szPath, &dwSize);
					if (ERROR_SUCCESS == lRet)
					{
						bVoiceAppRegistered = TRUE;
						SetDlgItemText(hDlg, IDC_VA_FEATURE, _T("Voice Dialing (using VoiceCommand)"));
					}
					RegCloseKey(hKey);
				}
				if (!bVoiceAppRegistered)
				{
					// try OEM key
					lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OEM_VOICE_APP, 0, 0, &hKey);
					if (ERROR_SUCCESS == lRet)
					{
						// On PPC, voice dialer app is listed in HKLM\\Software\\OEM\\VoiceCommand "Path"
						// read executable path
						dwSize = sizeof(szPath);
						dwType = 0;
						lRet = RegQueryValueEx(hKey, OEM_PATH, NULL, &dwType, (LPBYTE) &szPath, &dwSize);
						if (ERROR_SUCCESS == lRet)
						{
							bVoiceAppRegistered = TRUE;
							SetDlgItemText(hDlg, IDC_VA_FEATURE, _T("Voice Dialing (using OEM dialer)"));
						}
						RegCloseKey(hKey);
					}
				}
			}

			if (bVoiceAppRegistered)
			{
				// EnableWindow(TRUE) not needed since default is enabled unless disabled above
				// EnableWindow(GetDlgItem(hDlg, IDC_VA_FEATURE), TRUE);
				CheckDlgButton(hDlg, IDC_VA_FEATURE, g_dwHandleCKPD);
			}
			else
			{
				g_dwHandleCKPD = 0;
				EnableWindow(GetDlgItem(hDlg, IDC_VA_FEATURE), FALSE);
				CheckDlgButton(hDlg, IDC_VA_FEATURE, BST_UNCHECKED);
				if (bDisableVoice)
					SetDlgItemText(hDlg, IDC_VA_FEATURE, _T("Voice Dialing (Not supported)"));
				else
					SetDlgItemText(hDlg, IDC_VA_FEATURE, _T("Voice Dialing (No voice dialing application registered)"));
				// try SAPI Lite key
				lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SAPI_KEY, 0, 0, &hKey);
				if (ERROR_SUCCESS == lRet)
				{
					dwSize = sizeof(szPath);
					dwType = 0;
					lRet = RegQueryValueEx(hKey, SAPI_ENGINE, NULL, &dwType, (LPBYTE) &szPath, &dwSize);
					if (ERROR_SUCCESS == lRet)
					{
						SetDlgItemText(hDlg, IDC_VA_FEATURE, _T("Voice Dialing (use SAPI)"));
					}
					RegCloseKey(hKey);
				}
			}
			if (IsSmartphone())
			{
				ShowWindow(GetDlgItem(hDlg, IDC_SUSPEND_FEATURE), SW_HIDE);
				dwMaxRow = 12;
			}
			else
			{
				ShowWindow(GetDlgItem(hDlg, IDC_SUSPEND_FEATURE), SW_SHOW);
				CheckDlgButton(hDlg, IDC_SUSPEND_FEATURE, (g_dwSleepOnDisconnect) ? BST_CHECKED : BST_UNCHECKED);
				dwMaxRow = 13;
			}
			CheckDlgButton(hDlg, IDC_PB_FEATURE, (g_dwHandleCPBS) ? BST_CHECKED : BST_UNCHECKED);
			CheckDlgButton(hDlg, IDC_MSG_FEATURE, (g_dwHandleCPMS) ? BST_CHECKED : BST_UNCHECKED);
			CheckDlgButton(hDlg, IDC_CID_FEATURE, (g_dwHandleCLIP) ? BST_CHECKED : BST_UNCHECKED);
			CheckDlgButton(hDlg, IDC_IND_FEATURE, (g_dwHandleCIND) ? BST_CHECKED : BST_UNCHECKED);
			CheckDlgButton(hDlg, IDC_MER_FEATURE, (g_dwHandleCMER) ? BST_CHECKED : BST_UNCHECKED);
			CheckDlgButton(hDlg, IDC_CHUP_FEATURE, (g_dwHandleCHUP) ? BST_CHECKED : BST_UNCHECKED);
			/*
			if (bDisableVoice)
			{
				g_dwInBandRing = 0;
				EnableWindow(GetDlgItem(hDlg, IDC_IBRT_FEATURE), FALSE);
				SetDlgItemText(hDlg, IDC_IBRT_FEATURE, _T("Use phone ringtones (Not supported)"));
				CheckDlgButton(hDlg, IDC_IBRT_FEATURE, BST_UNCHECKED);
			}
			else
			*/
			CheckDlgButton(hDlg, IDC_IBRT_FEATURE, (g_dwInBandRing) ? BST_CHECKED : BST_UNCHECKED);

			SetupScrollbar(hDlg, IDC_IBRT_FEATURE, dwMaxRow+1);
			break;
        }
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
        case WM_COMMAND:
			ScrollToActiveControl(hDlg, wParam, IDC_PB_FEATURE, 4);
            switch (LOWORD(wParam)) 
            {
				/*
				case IDC_PB_FEATURE:
				{
					if (IsDlgButtonChecked(hDlg, IDC_PB_FEATURE))
					{
						DWORD dwRet = MessageBox(hDlg, _T("Disabling the Phonebooks feature will disable phonebook filters and limits."), _T("Notice"), MB_OKCANCEL);
						if (dwRet == IDCANCEL)
						{
							bProcessedMsg = true;
						}
					}
					break;
				}
				*/
				case IDM_IMPORT:
				{
					TCHAR   szFile[MAX_PATH] = _T("\0");
					OPENFILENAME   ofn;

					memset( &(ofn), 0, sizeof(ofn));
					ofn.lStructSize   = sizeof(ofn);
					ofn.hwndOwner = hDlg;
					ofn.lpstrFile = szFile;
					ofn.nMaxFile = MAX_PATH;   

					ofn.lpstrTitle = _T("Open settings file");
					ofn.lpstrFilter = _T("JETware config files (*.jcf)\0*.jcf\0");   
					ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;  
					if (GetOpenFileName(&ofn))
					{
						BOOL bRet = AddDeviceSettings(hDlg, szFile);
						if (bRet)
							MessageBox(hDlg, _T("Settings added successfully"), _T("Succeeded"), MB_OK);
						else
							MessageBox(hDlg, _T("Settings could not be added"), _T("Failed"), MB_OK);
					}
					break;
				}
				case IDOK:
					if (IsSmartphone())
					{
						bProcessedMsg = false;
						break;
					}
					// else intentionally fall through on PocketPC
                case ID_DONE:
				{
					HKEY    hKey                = NULL;
					DWORD   dwType              = 0;
					DWORD	dwSize				= 0;
					LONG	lRet				= 0;
					DWORD	dwValue				= 0;

					g_dwHandleCPBS = IsDlgButtonChecked(hDlg, IDC_PB_FEATURE);
					g_dwHandleCPMS = IsDlgButtonChecked(hDlg, IDC_MSG_FEATURE);
					g_dwHandleCLIP = IsDlgButtonChecked(hDlg, IDC_CID_FEATURE);
					g_dwHandleCIND = (IsDlgButtonChecked(hDlg, IDC_IND_FEATURE)) ? BST_INDETERMINATE : BST_UNCHECKED;
					g_dwHandleCMER = (IsDlgButtonChecked(hDlg, IDC_MER_FEATURE)) ? BST_INDETERMINATE : BST_UNCHECKED;
					g_dwHandleCHUP = (IsDlgButtonChecked(hDlg, IDC_CHUP_FEATURE)) ? BST_INDETERMINATE : BST_UNCHECKED;
					g_dwInBandRing = IsDlgButtonChecked(hDlg, IDC_IBRT_FEATURE);
					g_dwHandleCKPD = IsDlgButtonChecked(hDlg, IDC_VA_FEATURE);
					g_dwSleepOnDisconnect = IsDlgButtonChecked(hDlg, IDC_SUSPEND_FEATURE);

//					if (g_dwHandleCKPD)
					lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, RK_AUDIO_GATEWAY, 0, 0, &hKey);
					if (ERROR_SUCCESS == lRet)
					{
						// read Audio Gateway capabilities
						dwSize = sizeof(dwValue);
						dwType = 0;
						lRet = RegQueryValueEx(hKey, AG_CAPABILTY, NULL, &dwType, (LPBYTE) &dwValue, &dwSize);
						if (ERROR_SUCCESS != lRet)
						{
							dwValue = 0x21;
						}
						if (g_dwHandleCKPD)
							dwValue = (dwValue | 0x4);
						if (g_dwInBandRing)
							dwValue = (dwValue | 0x8);
						else
							dwValue = (dwValue & 0xFFF7);
						RegSetValueEx(hKey, AG_CAPABILTY, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(dwValue));

						RegCloseKey(hKey);
					}

					WriteFeatureSettings();
					// if (g_wSLA < SLA_EVALUATION)
					//	ShowExpiredMessage(hDlg);
				}
                case IDCANCEL:
                    EndDialog(hDlg, 0);
					// hActiveChild = NULL;
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
        
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

BOOL CALLBACK AboutDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
            break;

        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
			mbi.nToolBarId  = IDR_DIALOG_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

			TCHAR szTitle[64];
			GetWindowText(GetParent(hDlg), szTitle, 64);
			SetWindowText(hDlg, szTitle);

			GetModuleFileName(NULL, g_szAppPath, MAX_PATH);

			DWORD dwHandle = 0;
			DWORD dwSize = 0;
			UINT iLen = 0;
			TCHAR szVer[32];
			VOID * pVerData = NULL;
			VOID * pBlock = NULL;
			VS_FIXEDFILEINFO * pVerInfo = NULL;

			dwSize = GetFileVersionInfoSize(g_szAppPath, &dwHandle);
			if (dwSize) // Read version info from App
			{
				pVerData = LocalAlloc(LPTR, dwSize);
				if (pVerData != NULL)
				{
					if (GetFileVersionInfo(g_szAppPath, dwHandle, dwSize, pVerData))
					{
						if (VerQueryValue(pVerData, _T("\\"), &pBlock, &iLen))
						{
							pVerInfo = (VS_FIXEDFILEINFO *) pBlock;
							wsprintf(szVer, _T("Version %i.%i"), HIWORD(pVerInfo->dwProductVersionMS), 
								LOWORD(pVerInfo->dwProductVersionMS));
							SetDlgItemText(hDlg, IDC_PROD_VER, szVer);
							wsprintf(szVer, _T("%i.%i.%i.%i"), HIWORD(pVerInfo->dwFileVersionMS), 
								LOWORD(pVerInfo->dwFileVersionMS), HIWORD(pVerInfo->dwFileVersionLS),
								LOWORD(pVerInfo->dwFileVersionLS));
							SetDlgItemText(hDlg, IDC_CONFIG_VER, szVer);
						}
					}
					LocalFree(pVerData);
				}
			}
			dwSize = GetFileVersionInfoSize(g_szDllPath, &dwHandle);
			if (dwSize) // Read version info from App
			{
				pVerData = LocalAlloc(LPTR, dwSize);
				if (pVerData != NULL)
				{
					if (GetFileVersionInfo(g_szDllPath, dwHandle, dwSize, pVerData))
					{
						pBlock = NULL;
						iLen = 0;
						if (VerQueryValue(pVerData, _T("\\"), &pBlock, &iLen))
						{
							pVerInfo = (VS_FIXEDFILEINFO *) pBlock;
							wsprintf(szVer, _T("%i.%i.%i.%i"), HIWORD(pVerInfo->dwFileVersionMS), 
								LOWORD(pVerInfo->dwFileVersionMS), HIWORD(pVerInfo->dwFileVersionLS),
								LOWORD(pVerInfo->dwFileVersionLS));
							SetDlgItemText(hDlg, IDC_DLL_VER, szVer);
						}
					}
					LocalFree(pVerData);
				}
			}
			// Stretch Title header button to full width
			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);

			// Override the BACK key so we can send it to the edit control
			// SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
			SetupScrollbar(hDlg, IDC_PROD_VER, 7);
            break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
		case WM_SIZE:
			ResizeDialog(hDlg, IDC_PROD_VER, NULL);
			break;
		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            {
				case IDOK:
					if (IsSmartphone())
					{
						bProcessedMsg = false;
						break;
					}
                case ID_DONE:
                case IDCANCEL:
                    EndDialog(hDlg, 0);
					// hActiveChild = NULL;
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
        
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

BOOL CALLBACK ChooseDeviceDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
            break;

        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
#ifdef DEBUG
			CHAR szLog[128];
			sprintf(szLog, "Init ChooseDeviceDialog for device %S", (TCHAR *) lParam);
			LogString(szLog);
#endif
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
			mbi.nToolBarId  = IDR_DIALOG_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

			TCHAR szTitle[256];
			if (GetParent(hDlg) != NULL)
				GetWindowText(GetParent(hDlg), szTitle, 64);
			else
				wcscpy(szTitle, _T("Hands-free Settings"));
			SetWindowText(hDlg, szTitle);

			TCHAR szValue[256];
			szDeviceName = (TCHAR *) lParam;
			int nLen = wcslen(szDeviceName);
			WORD wCount = 1;
			HRESULT hr                  = S_OK;
			HKEY    hKey                = NULL;
			DWORD   dwType              = 0;
			DWORD	dwSize				= 0;
			DWORD	wValue				= 0;
			HWND	hListBox			= GetDlgItem(hDlg, IDC_DEVICE_LIST);

			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("[All devices]"));
			// Read list of HF device names from registry
			wsprintf(szValue, _T("%ls\\%i"), RK_AUDIO_GATEWAY_DEVICES, wCount++);

			while (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szValue, 0, 0, &hKey))
			{
				BYTE hfAddr[16];
				// Get Address from first device in AudioGateway Device list
				dwSize = sizeof(hfAddr);
				wValue = 0;
				dwType = 0;
				RegQueryValueEx(hKey, _T("Address"), NULL, &dwType, hfAddr, &dwSize);
				if (dwSize && (dwType == REG_BINARY))
				{
					wsprintf(szValue, _T("SOFTWARE\\Microsoft\\Bluetooth\\device\\%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X"),
						hfAddr[5], hfAddr[4], hfAddr[3], hfAddr[2], hfAddr[1], hfAddr[0]);
					RegCloseKey(hKey);

					if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szValue, 0, 0, &hKey))
					{
						dwSize = sizeof(szValue);
						wValue = 0;
						dwType = 0;
						RegQueryValueEx(hKey, _T("name"), NULL, &dwType, (LPBYTE) &szValue, &dwSize);
						if (dwSize && (dwType == REG_SZ))
						{
#ifdef DEBUG
							sprintf(szLog, "Found device %S", szValue);
							LogString(szLog);
#endif
							if (wcsncmp(szValue, szDeviceName, nLen) == 0)
							{
								wcscpy(szDeviceName, szValue);
								EndDialog(hDlg, IDOK);
							}
							else
							{
								SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) szValue);
							}
						}
					}
				}
				if (hKey != NULL)
					RegCloseKey(hKey);
				// Read next HF device name from registry
				wsprintf(szValue, _T("%ls\\%i"), RK_AUDIO_GATEWAY_DEVICES, wCount++);
			}

			SendMessage(hListBox, LB_SETCURSEL, 0, 0);
			GetWindowText(GetDlgItem(hDlg, IDC_NOMATCH), szTitle, 256);
			wsprintf(szValue, szTitle, szDeviceName);
			SetWindowText(GetDlgItem(hDlg, IDC_NOMATCH), szValue);
			// Stretch Title header button to full width
			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
#ifdef DEBUG
			sprintf(szLog, "ImportDlg:WM_INIT %i,%i,%i,%i", rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom);
			LogString(szLog);
#endif
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);

			// Override the BACK key so we can send it to the edit control
			// SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));

			SetupScrollbar(hDlg, IDC_DEVICE_LIST, 8);
			HWND hParent = GetParent(hDlg);
			if (hParent == NULL)
			{
				SetForegroundWindow(hDlg);
			}
			// SetCursor(NULL);
            break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
		case WM_SIZE:
		{
			ResizeDialog(hDlg, IDC_DEVICE_LIST, NULL);
			break;
		}
		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            {
				case IDOK:
					if (IsSmartphone())
					{
						bProcessedMsg = false;
						break;
					}
                case ID_DONE:
					SendDlgItemMessage(hDlg, IDC_DEVICE_LIST, LB_GETTEXT,
						SendDlgItemMessage(hDlg, IDC_DEVICE_LIST, LB_GETCURSEL, 0, 0), (LPARAM) szDeviceName);
					if (wcscmp(_T("[All devices]"), szDeviceName) == 0)
						szDeviceName[0] = 0;
                case IDCANCEL:
                    EndDialog(hDlg, LOWORD(wParam));
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
        
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}

BOOL CALLBACK BeamOptionsDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam)
{
    BOOL bProcessedMsg   = true;

    switch(uiMessage)
    {
        case WM_HOTKEY:
            // BACK key will come to us this way since we requested it in WM_INITDIALOG
			/*
            if(VK_TBACK == HIWORD(lParam))
            {
                SHSendBackToFocusWindow(uiMessage, wParam, lParam);
            }
			*/
            break;

        case WM_INITDIALOG:
        {
            // Specify that the dialog box should stretch full screen
#ifdef DEBUG
			CHAR szLog[128];
			// sprintf(szLog, "Init BeamOptionsDialog", (TCHAR *) lParam);
			LogString("Init BeamOptionsDialog");
#endif
            SHINITDLGINFO shidi;
            ZeroMemory(&shidi, sizeof(shidi));
            shidi.dwMask = SHIDIM_FLAGS;
            shidi.dwFlags = SHIDIF_SIZEDLGFULLSCREEN;
            if (!IsSmartphone())
            {
                shidi.dwFlags = shidi.dwFlags | SHIDIF_DONEBUTTON;
            }
            shidi.hDlg = hDlg;

            // If we could not initialize the dialog box, return an error
            if (!SHInitDialog(&shidi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

            // set up Soft Keys menu
            SHMENUBARINFO mbi;
            ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
            mbi.cbSize      = sizeof(SHMENUBARINFO);
            mbi.hwndParent  = hDlg;
			mbi.nToolBarId  = IDR_DIALOG_MENU;
            mbi.hInstRes    = g_hInst;

            // If we could not initialize the dialog box, return an error
            if (!SHCreateMenuBar(&mbi)) 
            {
                MessageBox( hDlg, _T("Error creating dialog"), _T("Error"), MB_OK | MB_ICONSTOP );
                EndDialog(hDlg, -1);
                return TRUE;
            }

			TCHAR szTitle[256];
			if (GetParent(hDlg) != NULL)
				GetWindowText(GetParent(hDlg), szTitle, 64);
			else
				wcscpy(szTitle, _T("Hands-free Settings"));
			SetWindowText(hDlg, szTitle);

			LRESULT lRes;
			HWND	hListBox			= GetDlgItem(hDlg, IDC_FORMAT_LIST);
			lRes = SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("File As"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("Last, First"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("Last, F"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("Last First"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("Last F"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("First Last"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("F Last"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("First L"));
			SendMessage(hListBox, LB_SETCURSEL, 0, 0);

			hListBox = GetDlgItem(hDlg, IDC_ENCODE_LIST);
			lRes = SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("GSM"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("UTF-8"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("UCS2"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("7-Bit"));
			SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM) _T("8-Bit"));
			SendMessage(hListBox, LB_SETCURSEL, 0, 0);

			CheckDlgButton(hDlg, IDC_VCARD_PER_NUMBER, g_dwNumbersPerCard);
			SetDlgItemInt(hDlg, IDC_MAX_NUMBERS, g_dwNumbersPerContact, FALSE);
			SendDlgItemMessage(hDlg, IDC_FORMAT_LIST, LB_SETCURSEL, g_dwFNFormat, 0);
			SetDlgItemInt(hDlg, IDC_MAX_NAMELEN, g_dwMaxNameLen, FALSE);
			SendDlgItemMessage(hDlg, IDC_ENCODE_LIST, LB_SETCURSEL, g_dwEncode, 0);
			// Stretch Title header button to full width
			RECT rectHdr;
			RECT rectDlg;
			GetClientRect(GetDlgItem(hDlg, IDC_TITLE), &rectHdr);
			GetWindowRect(hDlg, &rectDlg);
			rectHdr.right = rectDlg.right;
#ifdef DEBUG
			sprintf(szLog, "BeamOptionsDlg:WM_INIT %i,%i,%i,%i", rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom);
			LogString(szLog);
#endif
			SetWindowPos(GetDlgItem(hDlg, IDC_TITLE), hDlg, rectHdr.left, rectHdr.top, rectHdr.right, rectHdr.bottom,
				SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);

			// Override the BACK key so we can send it to the edit control
			// SendMessage(mbi.hwndMB, SHCMBM_OVERRIDEKEY, VK_TBACK, MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY));

			SetupScrollbar(hDlg, IDC_VCARD_PER_NUMBER, 10);
			HWND hParent = GetParent(hDlg);
			if (hParent == NULL)
			{
				SetForegroundWindow(hDlg);
			}
			// SetCursor(NULL);
            break;
        }
		case WM_DRAWITEM:
		{
			// redraw a listview item...called for each item
			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
			
			if (lpdis->CtlType == ODT_BUTTON)
			{
				DrawTitleHeader(hDlg, lpdis);
			}
            bProcessedMsg = false;
            break;
		}
		case WM_SIZE:
		{
			ResizeDialog(hDlg, IDC_VCARD_PER_NUMBER, NULL);
			break;
		}
		case WM_VSCROLL:
			ScrollDialog(hDlg, wParam);
			break;
		case WM_ACTIVATE:
			// Notify shell of our activate message
			SHHandleWMActivate(hDlg, wParam, lParam, &s_sai, FALSE);
			break;
		case WM_SETTINGCHANGE:
			SHHandleWMSettingChange(hDlg, wParam, lParam, &s_sai);
			break;
        case WM_COMMAND:
			ScrollToActiveControl(hDlg, wParam, IDC_ENCODE_LIST, 5);
            switch (LOWORD(wParam)) 
            {
				case IDOK:
					if (IsSmartphone())
					{
						bProcessedMsg = false;
						break;
					}
                case ID_DONE:
					g_dwNumbersPerCard = IsDlgButtonChecked(hDlg, IDC_VCARD_PER_NUMBER);
					g_dwNumbersPerContact = GetDlgItemInt(hDlg, IDC_MAX_NUMBERS, NULL, FALSE);
					g_dwFNFormat = SendDlgItemMessage(hDlg, IDC_FORMAT_LIST, LB_GETCURSEL, 0, 0);
					g_dwMaxNameLen = GetDlgItemInt(hDlg, IDC_MAX_NAMELEN, NULL, FALSE);;
					g_dwEncode = SendDlgItemMessage(hDlg, IDC_ENCODE_LIST, LB_GETCURSEL, 0, 0);
                case IDCANCEL:
                    EndDialog(hDlg, LOWORD(wParam));
                    break;

                default:
                    bProcessedMsg = false;
                    break;
            }
        
        default:
            // nothing was processed
            bProcessedMsg = false;
            break;
    }

    return bProcessedMsg;
}


// end JetBTConfig.cpp
